package com.yuebao.service.impl;


import cn.hutool.core.date.DateTime;
import com.alibaba.fastjson.JSON;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.yuebao.api.PaymentService;

import com.yuebao.config.AlipayProperties;
import com.yuebao.constant.OrderConstants;
import com.yuebao.event.EventDTO;
import com.yuebao.event.EventType;
import com.yuebao.exception.CustomerException;
import com.yuebao.feign.TransactionCloud;
import com.yuebao.mapper.MqProducerTempMapper;
import com.yuebao.mapper.TradePayMapper;
import com.yuebao.model.dto.ReduceStock;
import com.yuebao.model.dto.StockMqProducerTempLog;
import com.yuebao.model.pojo.FundProduction;
import com.yuebao.model.pojo.Transaction;
import com.yuebao.model.vo.PayAsynDTO;

import com.yuebao.request.TransactionDTO;
import com.yuebao.result.BaseResponse;

import com.yuebao.sender.CommonSender;

import com.yuebao.utils.CacheClient;
import com.yuebao.utils.IDWorker;
import com.yuebao.utils.JsonUtils;
import com.yuebao.utils.ResponseUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.spring.core.RocketMQTemplate;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@Transactional
public class PaymentServiceImpl  implements PaymentService {

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    @Resource
    private TradePayMapper tradePayMapper;

    @Resource
    private MqProducerTempMapper mqProducterTempMapper;

    @Resource
    private IDWorker idWorker;
    
    @Resource
    AlipayProperties alipayProperties;
    
    @Resource
    private CacheClient cacheClient;
    
    @Resource
    private TransactionCloud transactionCloud;
    
    @Resource
    private CommonSender commonSender;
    
    @Override
    public void handlePaymentResult(PayAsynDTO payResult) throws Exception {
        
    
        //验签
        checkSignature(payResult);
        //验订单
        TransactionDTO transactionDTO = checkOrder(payResult);
    
        //更新状态
        BaseResponse updateResponse = transactionCloud.updateTransactionState(payResult.getOut_trade_no(),OrderConstants.FINISHED);
        if(!updateResponse.isResponseRight()){
            throw new CustomerException("更新状态失败");
        }
        //异步扣份额
        ReduceShare(transactionDTO);
        

    }
    
    private void ReduceShare(TransactionDTO transactionDTO) throws CustomerException {
        
        EventDTO eventDTO = EventDTO.builder()
                .msg(JsonUtils.writeValueAsString(transactionDTO))
                .type(EventType.REDUCE_FUND_STOCK)
                .build();
        
        StockMqProducerTempLog stockProducerLog =StockMqProducerTempLog.builder()
                .createTime(DateTime.now())
                .groupName("YUEBAO")
                .msgBody(JsonUtils.writeValueAsString(eventDTO))
                .msgTag("reduce-fund-stock")
                .msgTopic("fund-service")
                .msgStatus(1)
                .id(String.valueOf(idWorker.nextId()))
                .build();
    
        mqProducterTempMapper.insertMqLog(stockProducerLog);
        SendResult sendResult = commonSender.syncSend("fund-service","reduce-fund-stock",eventDTO);
        log.info(JsonUtils.writeValueAsString(sendResult.getSendStatus()));
        if(!sendResult.getSendStatus().equals(SendStatus.SEND_OK))
            throw new CustomerException("mq生产发送失败");
        //发送成功后删除日志
        mqProducterTempMapper.deleteById(stockProducerLog.getId());
        
        
    }
    
    private TransactionDTO checkOrder(PayAsynDTO payResult) throws CustomerException {
        TransactionDTO transactionDTO = transactionCloud.getOrderByOrderNo(payResult.getOut_trade_no());
        log.info("查询订单：{}",JsonUtils.writeValueAsString(transactionDTO));
        if(Objects.isNull(transactionDTO))
            throw new CustomerException("订单不存在");
        if(transactionDTO.getOrderState().equals(OrderConstants.FINISHED))
            throw new CustomerException("不要重复提交");
        else if(transactionDTO.getOrderState().equals(OrderConstants.FAIL))
            throw new CustomerException("无效的订单");
        return transactionDTO;
    }
    
    private void checkSignature(PayAsynDTO payDTO) throws JsonProcessingException, AlipayApiException, CustomerException {
//        String sign = payDTO.getSign();
//
//        String content = AlipaySignature.getSignCheckContentV1(JsonUtils.mapper.readValue(JsonUtils.writeValueAsString(payDTO),new TypeReference<Map<String ,String>>() {}));
//        boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign,alipayProperties.getAlipayPublicKey(), "UTF-8"); // 验证签名
        // 支付宝验签
        boolean checkSignature = true;
        if (!checkSignature) {
            // 验签不通过
            
            throw new CustomerException("验签失败");
        }
        if(payDTO.getTrade_status().equals("TRADE_FAIL")){
            BaseResponse updateResponse = transactionCloud.updateTransactionState(payDTO.getOut_trade_no(),OrderConstants.PAYFAIL);
            if(!updateResponse.isResponseRight()){
                System.out.println("xx");
                throw new CustomerException("更新状态失败");
                
            }
        }
    }
}
//    // 业务标识 选择器根据业务标识来保证同一个业务标识被发送到同一个队列，方便消费端按照顺序来处理同一个用户的消息
//    // 这里的用户标识 选择用户id todo
//    String userId= "lhc测试APP";
//    //把id序列化成数字然后取模来决定分配到哪个队列
//
//
//    // 初始化消息
//    Message message = new Message("fund-stock","reduce",userId, JSON.toJSONString(vo).getBytes());
//// 顺序同步消费
//        try {
//
//                SendResult sendResult = rocketMQTemplate.getProducer().send(message, new MessageQueueSelector(){
//@Override// 保证同一个用户顺序消费
//public MessageQueue select(List<MessageQueue> messageQueues, Message message, Object args) {
//        String userId = (String) args;
//        //字符串转换为数字 % 对同一个topic下的队列个数取模
//        //int index = userId.hashCode()%messageQueues.size();
//
//        long index= (long) (Math.random()*10+1)%messageQueues.size();
//        System.out.println("当前的index"+index);
//        return messageQueues.get((int) index); //发送到序号为index的队列
//        }
//        },userId);
//        System.out.println(userId+sendResult.getSendStatus()); //显示发送结果
//        } catch (MQClientException e) {
//        e.printStackTrace();
//        } catch (RemotingException e) {
//        e.printStackTrace();
//        } catch (MQBrokerException e) {
//        e.printStackTrace();
//        } catch (InterruptedException e) {
//        e.printStackTrace();
//        }
